/*
 *
 *  *    Copyright 2020-2021 Luter.me
 *  *
 *  *    Licensed under the Apache License, Version 2.0 (the "License");
 *  *    you may not use this file except in compliance with the License.
 *  *    You may obtain a copy of the License at
 *  *
 *  *      http://www.apache.org/licenses/LICENSE-2.0
 *  *
 *  *    Unless required by applicable law or agreed to in writing, software
 *  *    distributed under the License is distributed on an "AS IS" BASIS,
 *  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  *    See the License for the specific language governing permissions and
 *  *    limitations under the License.
 *
 */

package com.luter.heimdall.core.manager;


import com.luter.heimdall.core.context.WebContextHolder;
import com.luter.heimdall.core.details.UserDetails;
import com.luter.heimdall.core.jwt.JwtProcessor;
import com.luter.heimdall.core.listener.AuthEventListener;
import com.luter.heimdall.core.token.SimpleToken;
import com.luter.heimdall.core.token.id.IdGenerator;
import com.luter.heimdall.core.token.store.TokenStore;

import java.time.Duration;
import java.util.Collection;

/**
 * 认证管理器
 * <p>
 * 实现登录、注销、在线会话管理等功能
 * <p>
 * 支持 Session+cookie 模式和 jwt模式
 *
 * @author luter
 */
public interface AuthenticationManager {
    /// //////// //////// //////// 认证:登录注销、在线用户等 //////// //////// ////////

    /**
     * 登录
     * <p>
     * Cookie 开启的情况下
     * <p>
     * cookie 时长采用配置文件中的 Cookie.maxAge
     *
     * @param userDetails the user details
     * @return Token Id 或者 Jwt Token 密文
     */
    String login(UserDetails userDetails);

    /**
     * 登录，支持  "记住我" 功能
     * <p>
     * 仅在 Session+Cookie 模式下可用。
     *
     * @param userDetails the user details
     * @param maxAge      设置Cookie maxAge时长，单位:秒                    <p>                    会给客户端写入这个时长的 cookie。                    <p>                    在未开启 token 自动续期的情况下                    <p>                    时长不可以超过 token 的生命时长，否则前台有效，后台 token 失效了。
     * @return token 串
     */
    String login(UserDetails userDetails, Duration maxAge);

    /**
     * 获取当前登录用户信息
     *
     * @param isThrowEx 是否抛出异常
     * @return the current user 用户详情
     */
    UserDetails getCurrentUser(boolean isThrowEx);

    /**
     * 获取当前登录 Token 信息
     *
     * @param isThrowEx 是否抛出异常
     * @return 找不到 ，返回 null 或者抛出异常
     */
    SimpleToken getCurrentToken(boolean isThrowEx);

    /**
     * 判断当前请求用户是否已经登录
     *
     * @param isThrowEx 是否抛出异常
     * @return the boolean
     */
    boolean isAuthenticated(boolean isThrowEx);

    /**
     * 退出登录
     *
     * @return 退出用户的 Token
     */
    SimpleToken logout();

    //////////////////////////////会话管理/////////////////////////////////

    /**
     * 作废某个 Token
     * <p>
     * 作废 token 后，用户会话会被结束，会强制用户重新登录
     *
     * @param tokenId the token id
     * @return the user details
     */
    SimpleToken kickToken(String tokenId);

    /**
     * 根据principal  作废所有 tokens
     * <p>
     * 在允许单个用户多次重复登录的情况下，此操作会将所有活动会话 作废，会强制用户重新登录
     *
     * @param userDetails the user details
     * @return the int
     */
    int kickPrincipalTokens(UserDetails userDetails);

    /**
     * 将某个 应用下的所有登录用户都踢出
     * <p>
     * <p>
     * 这些用户将全部需要重新登录
     * <p>
     * 同时，这些用户的所有权限缓存也会一并被清理
     *
     * @param appId APP ID
     * @return the int  作废数量
     */
    int kickAppActiveTokens(String appId);

    /**
     * 获取某个用户的所有活动 tokens
     *
     * @param userDetails the user details
     * @return the principal tokens
     */
    Collection<SimpleToken> getPrincipalTokens(UserDetails userDetails);

    /**
     * 获取某个应用的所有活动 Token
     *
     * @param appId the app id
     * @return the active tokens
     */
    Collection<SimpleToken> getActiveTokens(String appId);

    /**
     * 获取所有应用的所有活动 tokens
     *
     * @return the active tokens
     */
    Collection<SimpleToken> getActiveTokens();

    //////// //////// //////// 监听器  //////// //////// ////////

    /**
     * 获取当前所有注册的 认证授权 监听器
     *
     * @return the listeners
     */
    Collection<AuthEventListener> getListeners();
    ////////////////////////////// 对象代理 /////////////////////////////////

    /**
     * 获取 TokenStore
     *
     * @return the token store
     */
    TokenStore getTokenStore();

    /**
     * 获取 web 上下文
     *
     * @return the request token resolver
     */
    WebContextHolder getWebContextHolder();

    /**
     * 获取 ID 生成器
     *
     * @return the id generator
     */
    IdGenerator getIdGenerator();

    /**
     * 获取 jwt 处理器
     *
     * @return the jwt processor
     */
    JwtProcessor getJwtProcessor();
}
